﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using ITAP.ShprossesBuilder.Render;
using ITAP.ShprossesBuilder.Info;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.ShprossesBuilder.Modelling;
using ITAP.ShprossesBuilder.Modelling.Components;
using ITAP.ShprossesBuilder.Editor;
using ITAP.ShprossesBuilder.Manipulation;
using ITAP.Core.Calculations;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder
{
    public delegate ProfilesInfo ProfilesProviderDelegate(Material[] materials);

    public partial class MaterialPanel : UserControl
    {
        private Orientation orientation;
        public Orientation Orientation
        {
            get
            {
                return orientation;
            }
            set
            {
                if (value == Orientation.Vertical)
                {
                    this.tabControlMaterials.HeaderLocation = DevExpress.XtraTab.TabHeaderLocation.Left;
                }
                else
                    this.tabControlMaterials.HeaderLocation = DevExpress.XtraTab.TabHeaderLocation.Bottom;
                orientation = value;
            }
        }

        public IComponent SelectedComponent
        {
            get
            {
                if (listViewConnectors.SelectedItems.Count != 0)
                    return listViewConnectors.SelectedItems[0].Tag as IComponent;
                if (listViewSnapOnCaps.SelectedItems.Count != 0)
                    return listViewSnapOnCaps.SelectedItems[0].Tag as IComponent;
                if (listViewSpacerConnectors.SelectedItems.Count != 0)
                    return listViewSpacerConnectors.SelectedItems[0].Tag as IComponent;
                if (listViewShprosses.SelectedItems.Count != 0)
                    return listViewShprosses.SelectedItems[0].Tag as IComponent;

                return null;
            }
        }

        private bool enabled = true;
        public bool Enabled
        {
            get
            {
                return enabled;
            }
            set
            {
                enabled = value;
                listViewConnectors.Enabled = value;
                listViewShprosses.Enabled = value;
                listViewSnapOnCaps.Enabled = value;
                listViewSpacerConnectors.Enabled = value;
            }
        }

        private ContextMenuStrip contextMenu;

        public ListView ConnectorsListView
        {
            get { return this.listViewConnectors; }
        }

        public ListView ShprossesListView
        {
            get { return this.listViewShprosses; }
        }

        public ListView SnapOnCapsListView
        {
            get { return this.listViewSnapOnCaps; }
        }

        private IComponent draggedComponent = null;

        public MaterialPanel()
        {
            InitializeComponent();
        }

        private ProfilesProviderDelegate profilesProviderDelegate;
        private SimpleRender thumbnailRender;
        private Material[] materials;
        private MainControl mainControl;

        private IComponent component;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="profilesProviderDelegate"></param>
        /// <param name="thumbnailRender"></param>
        /// <param name="thumbnailSize"></param>
        /// <param name="materials"></param>
        /// <param name="mainControl">Если не null, то двойной щелчок по профилю или соединителю создаст профиль или соединитель внутри активной модели.</param>
        /// <param name="component">Если не null, то будут показаны только те компоненты, с которыми может быть соединён компонент по ID.</param>
        public void Initialize(ProfilesProviderDelegate profilesProviderDelegate,
                               SimpleRender thumbnailRender,
                               Size thumbnailSize,
                               Material[] materials,
                               MainControl mainControl, 
                               IComponent component)
        {
            this.component = component;
            contextMenu = new ContextMenuStrip();
            contextMenu.Items.Add(new ToolStripMenuItem("Добавить в активную модель", null, new EventHandler(AddElementToActiveModel)));

            this.mainControl = mainControl;
            this.profilesProviderDelegate = profilesProviderDelegate;
            this.thumbnailRender = thumbnailRender;
            this.materials = materials;

            tabControlMaterials.TabPages.Clear();

            this.listViewConnectors.Clear();
            this.listViewShprosses.Clear();
            this.listViewSnapOnCaps.Clear();
            this.listViewSpacerConnectors.Clear();

            ModelCoordinateConverter coordinateConverter = new ModelCoordinateConverter();

            coordinateConverter.UseAutoScale = true;
            ImageList imageListConnectors = new ImageList();
            imageListConnectors.ColorDepth = ColorDepth.Depth32Bit;
            imageListConnectors.ImageSize = thumbnailSize;

            ImageList imageListProfiles = new ImageList();
            imageListProfiles.ColorDepth = ColorDepth.Depth32Bit;
            imageListProfiles.ImageSize = thumbnailSize;

            ImageList imageListSnapOnCaps = new ImageList();
            imageListSnapOnCaps.ColorDepth = ColorDepth.Depth32Bit;
            imageListSnapOnCaps.ImageSize = thumbnailSize;

            ImageList imageListSpacerConnectors = new ImageList();
            imageListSpacerConnectors.ColorDepth = ColorDepth.Depth32Bit;
            imageListSpacerConnectors.ImageSize = thumbnailSize;


            ProfilesInfo info = profilesProviderDelegate.Invoke(materials);


            if (info.Connectors.Count != 0)
                this.tabControlMaterials.TabPages.Add(this.tabPageConnectors);

            if (info.Shprosses.Count != 0)
                this.tabControlMaterials.TabPages.Add(this.tabPageProfiles);

            if (info.SnapOnCaps.Count != 0)
                this.tabControlMaterials.TabPages.Add(this.tabPageSnapOnCaps);

            if (info.SpacerConnectors.Count != 0)
                this.tabControlMaterials.TabPages.Add(this.tabPageSpacerConnectors);

            foreach (ITAP.ShprossesBuilder.Modelling.Components.IComponent connector in info.Connectors)
            {
                if (component != null && !component.AcceptedUniqueIdsToConnect.Contains(connector.UniqueId))
                    continue;

                connector.MoveToZeroPoint();
                RectangleF boundingBox = connector.BoundingBox;
                Graphics connectorsGraphics;
                Image thumbnail = new Bitmap(thumbnailSize.Width, thumbnailSize.Height);
                connectorsGraphics = Graphics.FromImage(thumbnail);
                connectorsGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                connectorsGraphics.Clear(Color.White);
                thumbnailRender.Initialize(connectorsGraphics, thumbnailSize.Width - 1, thumbnailSize.Height - 1, boundingBox, coordinateConverter, new ModelPoint(boundingBox.Width / 2, boundingBox.Height / 2));
                connector.AcceptVisitor(thumbnailRender);
                imageListConnectors.Images.Add(thumbnail);
                connectorsGraphics.Dispose();
            }

            this.listViewConnectors.LargeImageList = imageListConnectors;
            this.listViewConnectors.SmallImageList = imageListConnectors;

            foreach (ITAP.ShprossesBuilder.Modelling.Components.IComponent shpross in info.Shprosses)
            {
                if (component != null && !component.AcceptedUniqueIdsToConnect.Contains(shpross.UniqueId))
                    continue;

                Graphics profilesGraphics;
                RectangleF boundingBox = shpross.BoundingBox;
                shpross.MoveWithOffset(new ModelVector(-boundingBox.X, -boundingBox.Y));
                boundingBox = shpross.BoundingBox;
                Image thumbnail = new Bitmap(thumbnailSize.Width, thumbnailSize.Height);
                profilesGraphics = Graphics.FromImage(thumbnail);
                profilesGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                profilesGraphics.Clear(Color.White);

                ModelPoint shprossCenter = new ModelPoint((boundingBox.X + boundingBox.Width) / 2, (boundingBox.Y + boundingBox.Height / 2));
                thumbnailRender.Initialize(profilesGraphics, thumbnailSize.Width - 1, thumbnailSize.Height - 1, boundingBox, coordinateConverter, shprossCenter);
                shpross.AcceptVisitor(thumbnailRender);
                imageListProfiles.Images.Add(thumbnail);
                profilesGraphics.Dispose();
            }

            this.listViewShprosses.LargeImageList = imageListProfiles;
            this.listViewShprosses.SmallImageList = imageListProfiles;

            for (int connIter = 0; connIter < info.Connectors.Count; connIter++)
            {
                ListViewItem item = new ListViewItem(info.Connectors[connIter].Article, connIter);
                item.Tag = info.Connectors[connIter];
                this.listViewConnectors.Items.Add(item);
            }

            for (int shprossIter = 0; shprossIter < info.Shprosses.Count; shprossIter++)
            {
                ListViewItem item = new ListViewItem(info.Shprosses[shprossIter].Article, shprossIter);
                item.Tag = info.Shprosses[shprossIter];
                this.listViewShprosses.Items.Add(item);
            }

            this.listViewSnapOnCaps.LargeImageList = imageListSnapOnCaps;
            this.listViewSnapOnCaps.SmallImageList = imageListSnapOnCaps;
            foreach (ITAP.ShprossesBuilder.Modelling.Components.IComponent snapOnCap in info.SnapOnCaps)
            {
                if (component != null && !component.AcceptedUniqueIdsToConnect.Contains(snapOnCap.UniqueId))
                    continue;

                Graphics snapOnCapGraphics;
                snapOnCap.MoveToZeroPoint();
                RectangleF boundingBox = snapOnCap.BoundingBox;
                Image thumbnail = new Bitmap(thumbnailSize.Width, thumbnailSize.Height);
                snapOnCapGraphics = Graphics.FromImage(thumbnail);
                snapOnCapGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                snapOnCapGraphics.Clear(Color.White);

                thumbnailRender.Initialize(snapOnCapGraphics, thumbnailSize.Width - 1, thumbnailSize.Height - 1, boundingBox, coordinateConverter, new ModelPoint(boundingBox.Width / 2, boundingBox.Height / 2));
                snapOnCap.AcceptVisitor(thumbnailRender);
                imageListSnapOnCaps.Images.Add(thumbnail);
                snapOnCapGraphics.Dispose();
            }

            for (int snapOnCapIter = 0; snapOnCapIter < info.SnapOnCaps.Count; snapOnCapIter++)
            {
                ListViewItem item = new ListViewItem(info.SnapOnCaps[snapOnCapIter].Article, snapOnCapIter);
                item.Tag = info.SnapOnCaps[snapOnCapIter];
                this.listViewSnapOnCaps.Items.Add(item);
            }


            this.listViewSpacerConnectors.LargeImageList = imageListSpacerConnectors;
            this.listViewSpacerConnectors.SmallImageList = imageListSpacerConnectors;
            foreach (IComponent spacerConnector in info.SpacerConnectors)
            {
                if (component != null && !component.AcceptedUniqueIdsToConnect.Contains(spacerConnector.UniqueId))
                    continue;

                Graphics spacerConnectorGraphics;
                spacerConnector.MoveToZeroPoint();
                RectangleF boundingBox = spacerConnector.BoundingBox;
                Image thumbnail = new Bitmap(thumbnailSize.Width, thumbnailSize.Height);
                spacerConnectorGraphics = Graphics.FromImage(thumbnail);
                spacerConnectorGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                spacerConnectorGraphics.Clear(Color.White);

                thumbnailRender.Initialize(spacerConnectorGraphics, thumbnailSize.Width - 1, thumbnailSize.Height - 1, boundingBox, coordinateConverter, new ModelPoint(boundingBox.Width / 2, boundingBox.Height / 2));
                spacerConnector.AcceptVisitor(thumbnailRender);
                imageListSpacerConnectors.Images.Add(thumbnail);
                spacerConnectorGraphics.Dispose();
            }

            for (int spacerConnectorIter = 0; spacerConnectorIter < info.SpacerConnectors.Count; spacerConnectorIter++)
            {
                ListViewItem item = new ListViewItem(info.SpacerConnectors[spacerConnectorIter].Article, spacerConnectorIter);
                item.Tag = info.SpacerConnectors[spacerConnectorIter];
                this.listViewSpacerConnectors.Items.Add(item);
            }
        }

        private void listViewConnectors_MouseDown(object sender, MouseEventArgs e)
        {
            draggedComponent = null;
            if (e.Button == MouseButtons.Left)
            {
                if (listViewConnectors.SelectedItems.Count > 0)
                    this.DoDragDrop(listViewConnectors.SelectedItems[0], DragDropEffects.Copy);
            }
        }

        private void listViewShprosses_MouseDown(object sender, MouseEventArgs e)
        {
            listViewShprosses.HitTest(e.X, e.Y);
            draggedComponent = null;
            if (e.Button == MouseButtons.Left)
            {
                if (listViewShprosses.SelectedItems.Count > 0)
                {
                    DragDropEffects effects = this.DoDragDrop(listViewShprosses.SelectedItems[0], DragDropEffects.Copy);
                }
            }
        }

        private void listViewSnapOnCaps_MouseDown(object sender, MouseEventArgs e)
        {
            draggedComponent = null;
            if (e.Button == MouseButtons.Left)
            {
                if (listViewSnapOnCaps.SelectedItems.Count > 0)
                {
                    DragDropEffects effects = this.DoDragDrop(listViewSnapOnCaps.SelectedItems[0], DragDropEffects.Copy);
                }
            }
        }

        private void listViewSpacerConnectors_MouseDown(object sender, MouseEventArgs e)
        {
            draggedComponent = null;
            if (e.Button == MouseButtons.Left)
            {
                if (listViewSpacerConnectors.SelectedItems.Count > 0)
                    this.DoDragDrop(listViewSpacerConnectors.SelectedItems[0], DragDropEffects.Copy);
            }
        }

        public void SetThumbnailSize(Size size)
        {
            this.Initialize(profilesProviderDelegate, thumbnailRender, size, materials, mainControl, component);
        }

        private void listViewConnectors_MouseDoubleClick(object sender, MouseEventArgs e)
        {

        }

        private void listViewShprosses_MouseDoubleClick(object sender, MouseEventArgs e)
        {

        }

        private void listViewShprosses_DoubleClick(object sender, EventArgs e)
        {

        }

        //    private IComponent componentToAdd = null;

        private void listViewShprosses_MouseClick(object sender, MouseEventArgs e)
        {
            draggedComponent = null;
            if (e.Button == MouseButtons.Right)
            {
                if (listViewShprosses.SelectedItems.Count > 0)
                {
                    draggedComponent = listViewShprosses.SelectedItems[0].Tag as IComponent;
                    contextMenu.Show(listViewShprosses.PointToScreen(e.Location));
                }
            }
        }

        private void AddElementToActiveModel(object sender, EventArgs e)
        {
            if (this.mainControl != null)
            {
                if (this.mainControl.ModelControl.ModelContainer.ActiveCell != null)
                {
                    ModelCell cell = this.mainControl.ModelControl.ModelContainer.ActiveCell as ModelCell;
                    IModelComponentCommand addComponentCommand = new CommandEditorAddComponentToModel(mainControl.ModelControl, new Type[] { typeof(ShprossEndToEndConnector), typeof(CrossConnector), typeof(StickConnector), typeof(Shpross), typeof(SpacerConnector), typeof(ShprossConnector), typeof(Model) }, "");
                    PointF point = this.mainControl.ModelControl.ModelToScreen(new ModelPoint(cell.Model.BoundingBox.X + cell.Model.BoundingBox.Width / 2, cell.Model.BoundingBox.Y + cell.Model.BoundingBox.Height / 2));
                    Point _point = new Point((int)point.X, (int)point.Y);
                    addComponentCommand.MouseDownPoint = _point;
                    addComponentCommand.MouseMovePoint = _point;
                    addComponentCommand.MouseUpPoint = _point;
                    addComponentCommand.ComponentsForProcessing.Add((IComponent)draggedComponent.Clone());
                    this.mainControl.Manipulator.StartExecute(addComponentCommand);
                    this.mainControl.Manipulator.Execute(addComponentCommand);
                    this.mainControl.Manipulator.EndExecute(addComponentCommand);
                }
            }
        }

        private void listViewConnectors_MouseClick(object sender, MouseEventArgs e)
        {
            draggedComponent = null;
            if (e.Button == MouseButtons.Right)
            {
                if (listViewConnectors.SelectedItems.Count > 0)
                {
                    draggedComponent = listViewConnectors.SelectedItems[0].Tag as IComponent;
                    contextMenu.Show(listViewConnectors.PointToScreen(e.Location));
                }
            }
        }

        private void listViewConnectors_MouseMove(object sender, MouseEventArgs e)
        {
            draggedComponent = null;
            if (e.Button == MouseButtons.Left)
            {
                if (listViewConnectors.SelectedItems.Count > 0)
                    this.DoDragDrop(listViewConnectors.SelectedItems[0], DragDropEffects.Copy);
            }
        }

        private void listViewConnectors_GiveFeedback(object sender, GiveFeedbackEventArgs e)
        {

        }

        private void listViewConnectors_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
        {

        }
    }
}
